/*
 * main.cpp
 *
 *  Created on: Apr 10, 2011
 *      Author: Matthew Michelotti
 */

#include <sfv/centrality.h>
#include <sfv/components.h>
#include <sfv/print.h>

#include <sfv/array2d.h>
#include <sfv/gallery/forestfire.h>
#include <sfv/layout/Layout.h>

#include "GraphWindow.h"
#include "HNode.h"
#include <iostream>
#include <sfv/io/snap_matrix.h>
using namespace std;


typedef unsigned int uint;

int hnodeTestMain() {
	int numNodes = 6;
	int groupSize = 2;

	sfv::csr_matrix<int,float> A;
	sfv::gallery::forest_fire_game(A,numNodes,0.5,0.3,numNodes/17+1);
	sfv::print(A);

	vector<HNode*> hnodes;
	HNode::makeNodes(A, hnodes);

	sfv::csr_matrix<int, float> B;
	HNode::toMatrix(hnodes, B);
	sfv::print(B);

	vector<HNode*> parents;

	for(int i = 0; i < numNodes; i += groupSize) {
		vector<HNode*> children;
		for(int j = i; j < i+groupSize; j++) {
			children.push_back(hnodes[j]);
		}
		parents.push_back(HNode::formParent(children));
	}

//	for(uint i = 0; i < hnodes.size(); i++) {
//		hnodes[i]->print();
//	}
//
//	for(uint i = 0; i < parents.size(); i++) {
//		parents[i]->print();
//	}

	HNode::toMatrix(parents, B);
	sfv::print(B);
	return 0;
}

int basicVisNodeMain() {
	int numNodes = 20;

	sfv::csr_matrix<int,float> A;
	//sfv::gallery::forest_fire_game(A,numNodes,.001, .001,4);
	sfv::io::read_matrix_market_file(A, "ca-GrQc.txt");

	sfv::array1d<double> x(numNodes);
	sfv::array1d<double> y(numNodes);
	sfv::layout::Layout::random(A,x,y);

	GraphWindow::begin(A, x, y);
	return 0;
}

void mergeNodes(vector<HNode*>& nodes, uint numGroups, sfv::array1d<int>& membership) {

	vector<HNode*> result;
	vector< vector<HNode*> > groupVectors(numGroups);

	for(uint node = 0; node < membership.size(); node++) {
		groupVectors[membership[node]].push_back(nodes[node]);
	}

	for(uint group = 0; group < numGroups; group++) {
		result.push_back(HNode::formParent(groupVectors[group]));
	}

	nodes = result;
}

void mergeNodes(vector<HNode*>& nodes, uint numGroups) {
	vector<HNode*> result;

	//int groupSize = nodes.size()/numGroups;
	int nodeI = 0;
	for(uint group = 0; group < numGroups; group++) {
		vector<HNode*> groupVector;
		int endNodeI = (nodes.size()*(group+1))/numGroups;
		for(; nodeI < endNodeI; nodeI++) {
			groupVector.push_back(nodes[nodeI]);
		}
//		for(uint i = groupSize*group; i < groupSize*(group+1); i++) {
//			groupVector.push_back(nodes[i]);
//		}
		result.push_back(HNode::formParent(groupVector));
	}

	nodes = result;
}

int hiearchyVisNodeMain() {
	sfv::csr_matrix<int,float> A;

//	int numNodes = 1000;
//	sfv::gallery::forest_fire_game(A,numNodes,0.5,0.3,numNodes/17+1);
	sfv::io::read_matrix_market_file(A, "ca-GrQc.txt");

	/*sfv::array1d<double> result(A.num_rows);
	sfv::array1d<int> vids(A.num_rows);
	for( size_t i = 0; i < A.num_rows; i++)
		vids[i] = i;

	sfv::node_betweenness( A, result, vids );
	float max_betweenness = *std::max_element(result.begin(), result.end());

	size_t groupSize = 10;
	float binSize = max_betweenness / float(groupSize);
	sfv::array1d<int> membership(A.num_rows);
	sfv::array1d<int> histogram(groupSize+1);
	for( size_t i = 0; i < groupSize+1; i++)
		histogram[i] = 0;


	for( size_t i = 0; i < A.num_rows; i++ ){
		membership[i] = floor(result[i]/float(binSize)) + (result[i] != 0);
		histogram[membership[i]]++;
	}
	sfv::print(histogram);*/

	vector<HNode*> hnodes;
	HNode::makeNodes(A, hnodes);

	//mergeNodes( hnodes, groupSize+1, membership );


	mergeNodes(hnodes, 2187);
	mergeNodes(hnodes, 729);
	mergeNodes(hnodes, 243);
	mergeNodes(hnodes, 81);
	mergeNodes(hnodes, 27);
	mergeNodes(hnodes, 9);
	mergeNodes(hnodes, 3);
	//mergeNodes(hnodes, 1);

	GraphWindow::begin(hnodes[0]);

	return 0;
}

int readFileTestMain() {
	sfv::csr_matrix<int, float> A;
	sfv::io::read_matrix_market_file(A, "ca-GrQc.txt");

	std::cout << "Matrix has " << A.num_rows << " nodes and " << A.num_entries
			<< " edges." << std::endl;
	return 0;
}

int main(int argc, char** argv) {
//	return readFileTestMain();
//	return hnodeTestMain();
//	return basicVisNodeMain();
	return hiearchyVisNodeMain();
}


